package lab1;

import java.io.*;
import java.net.ServerSocket;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HttpProxy {
    private String configuration = "./src/lab1/configuration.txt"; //默认配置文件路径
    private int socketTimeOut = 1000;// 默认socket的超时时间为1000ms
    private Set<String> userFilter = new HashSet<>();// 默认不开启用户过滤
    private Set<String> webFilter = new HashSet<>();// 默认不开启网页过滤
    private final Map<String, String> fishing = new HashMap<>();// 默认不开启网站引导钓鱼
    private int serverPort = 10240;//默认监听端口号
    private int hit = 0;//保存命中的缓存数，便于分析结果
    private int maxCacheSize = 10;//用于规定最多缓存的文件数量

    public int getSocketTimeOut() {
        return socketTimeOut;
    }

    public Set<String> getUserFilter() {
        return userFilter;
    }

    public Set<String> getWebFilter() {
        return webFilter;
    }

    public Map<String, String> getFishing() {
        return fishing;
    }

    public int getHit() {
        return hit;
    }

    public void upDateHit() {
        hit++;
    }

    public HttpProxy() {
    }

    public HttpProxy(String configuration) {
        this.configuration = configuration;
    }

    /**
     * 启动代理服务器，开始处理客户端的HTTP请求
     */
    public void start_proxy() {
        configure(configuration);
        try {
            // 用于监听客户端请求的套接字
            // 默认的监听端口号
            ServerSocket serverSocket = new ServerSocket(serverPort);// 新建一个与客户端通信的套接字
            System.out.println("*************************************************************************************");
            System.out.println("监听端口:\t" + serverPort);
            if (!userFilter.isEmpty()) {
                System.out.println("用户过滤:\t" + userFilter);
            }
            if (!webFilter.isEmpty()) {
                System.out.println("目的网站过滤:\t" + webFilter);
            }
            if (!fishing.isEmpty()) {
                System.out.println(("网站钓鱼引导:\t" + fishing).replace("="," >>> "));
            }
            System.out.println("缓存最大文件数:\t" + maxCacheSize);
            System.out.println("*************************************************************************************");
            while (true) {// 不断监听来自客户端的请求
                new CommunicationThread(serverSocket.accept(), this).start();// 新建子线程处理连接请求
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * 从配置文件中读取配置
     *
     * @param filepath 配置路径
     */
    private void configure(String filepath) {
        try {
            StringBuilder stringBuilder = new StringBuilder();
            BufferedReader br = new BufferedReader(new FileReader(filepath));
            String line = br.readLine();
            while (line != null) {
                stringBuilder.append(line.strip()).append('\t');
                line = br.readLine();
            }
            br.close();
            String string = stringBuilder.toString();
            //配置serverPort
            Matcher matcher = Pattern.compile("serverPort:.+?\t").matcher(string);
            if (matcher.find()) {
                serverPort = Integer.parseInt(matcher.group().split(":")[1].strip());
            }
            //配置maxCacheSize
            matcher = Pattern.compile("maxCacheSize:.+?\t").matcher(string);
            if (matcher.find()) {
                maxCacheSize = Integer.parseInt(matcher.group().split(":")[1].strip());
            }
            // 配置socketTimeOut
            matcher = Pattern.compile("socketTimeOut:.+?\t").matcher(string);
            if (matcher.find()) {
                socketTimeOut = Integer.parseInt(matcher.group().split(":")[1].strip());
            }
            // 配置WebFilter
            matcher = Pattern.compile("WebFilter:.+?\t").matcher(string);
            if (matcher.find()) {
                webFilter = new HashSet<>(List.of(matcher.group().split(":")[1].strip().split(" ")));
            }
            // 配置WebFilter
            matcher = Pattern.compile("UserFilter:.+?\t").matcher(string);
            if (matcher.find()) {
                userFilter = new HashSet<>(List.of(matcher.group().split(":")[1].strip().split(" ")));
            }
            // 配置fishing
            matcher = Pattern.compile("fishing:.+?\t").matcher(string);
            if (matcher.find()) {
                String[] temp = matcher.group().split(":")[1].strip().split(" ");
                for (String i : temp) {
                    fishing.put(i.split(",")[0], i.split(",")[1]);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *检查缓存大小，如果缓存大于maxCacheSize，则删除最先缓存的文件。
     * @param cacheFileBase 缓存基地址
     * @return 删除的缓存文件，如果没有，则为空
     */
    public String checkCacheMemoryLeft(String cacheFileBase){
        String [] directory = new File(cacheFileBase).list();
        if (directory==null){
            return null;
        }
        long toDeleteTime = Long.MAX_VALUE;
        File toDeleteFile = null;
        int count = 0;
        for (String string : directory){
            if (!string.startsWith(".")) {
                File[] files = new File(cacheFileBase+string+"/").listFiles();
                if (files == null) {
                    return null;
                }
                for (File file : files){
                    count++;
                    if (file.lastModified()<toDeleteTime){
                        toDeleteTime = file.lastModified();
                        toDeleteFile = file;
                    }
                }
            }
        }
        if (toDeleteFile == null || count<maxCacheSize) {
            return null;
        }
        if (!toDeleteFile.delete()){
            System.out.println("删除文件失败！");
        }
        return toDeleteFile.toString();
    }

    public static void main(String[] args) {
        String configuration = "./src/lab1/configuration.txt";
        new HttpProxy(configuration).start_proxy();
    }
}
